package com.toolkit.util;

import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;

import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.text.*;
import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Arrays;


public class ExcelConvertToPdf {
    private static final Logger log = LoggerFactory.getLogger(ExcelConvertToPdf.class);

    /**
     * excel转PDF
     * @param excelFilePath
     * @param pdfFilePath
     * @throws Exception
     */
    public static void convertExcelToPdf(String excelFilePath, String pdfFilePath) throws Exception {
        Workbook workbook = WorkbookFactory.create(new FileInputStream(excelFilePath));
        PdfWriter writer = new PdfWriter(pdfFilePath);
        PdfDocument pdfDoc = new PdfDocument(writer);
        Document document = new Document(pdfDoc);

        for (Sheet sheet : workbook) {
            Table table = new Table(UnitValue.createPercentArray(sheet.getRow(0).getPhysicalNumberOfCells()));
            for (Row row : sheet) {
                for (Cell cell : row) {
                    table.addCell(new com.itextpdf.layout.element.Cell().add(new com.itextpdf.layout.element.Paragraph(cell.toString())));
                }
            }
            document.add(table);
        }

        document.close();
        pdfDoc.close();
        workbook.close();
    }

    public static void converToPdf(String excelFilePath, String pdfFilePath) throws Exception {
        Workbook workbook = WorkbookFactory.create(new FileInputStream(excelFilePath));
        PdfWriter writer = new PdfWriter(pdfFilePath);
        PdfDocument pdfDoc = new PdfDocument(writer);

        // 获取第一个工作表
        Sheet sheet = workbook.getSheetAt(0);
        // 创建PDF文档对象
//        int colWidth = getColWidth(sheet);
//        PageSize pageSize;
//        if (colWidth <= 21000){
//            pageSize = PageSize.A4;
//        } else if (colWidth <= 29700){
//            pageSize = PageSize.A3;
//        } else if (colWidth <= 42000){
//            pageSize = PageSize.A4.rotate();
//        } else {
//            pageSize = PageSize.A3.rotate();
//        }
        Document document = new Document(pdfDoc);
        BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font contentFont = new Font(baseFont, 36, Font.NORMAL);
        contentFont.setColor(BaseColor.BLACK);
        Paragraph content = new Paragraph();
        content.add(new Chunk());
        //设置基础中文字体
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);

        //给字体添加样式

        BaseFont baseFontChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        //中文字体
        final Font fontChinese = new Font(bfChinese, 16, Font.NORMAL);
        //非中文字体
        final Font fontNotChinese = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.NORMAL);

        //设置文字导出时的字体
        //document.add(getParagraph("", fontChinese, fontNotChinese));
        // 创建PDF表格对象
        float[] colWidthRatio = getColWidthRatio(sheet);
        Table table = new Table(colWidthRatio, true);

        // 添加表格内容
        for (Row row : sheet) {
            for (org.apache.poi.ss.usermodel.Cell cell : row) {
                com.itextpdf.layout.element.Cell addCell = new com.itextpdf.layout.element.Cell().add(new com.itextpdf.layout.element.Paragraph(cell.toString()));

                table.addCell(addCell);
            }
        }
        // 添加表格到PDF文档
        document.add(table);
        // 关闭PDF文档
        document.close();
    }

    public static void converter(SXSSFWorkbook workbook, FileOutputStream fos) {
        try  {
            // 获取第一个工作表
            Sheet sheet = workbook.getSheetAt(0);
            // 创建PDF文档对象
            int colWidth = getColWidth(sheet);
            PageSize pageSize;
            if (colWidth <= 21000){
                pageSize = PageSize.A4;
            } else if (colWidth <= 29700){
                pageSize = PageSize.A3;
            } else if (colWidth <= 42000){
                pageSize = PageSize.A4.rotate();
            } else {
                pageSize = PageSize.A3.rotate();
            }
            PdfWriter pdfWriter = new PdfWriter(fos);
            PdfDocument pdfDocument = new PdfDocument(pdfWriter);
            Document document = new Document(pdfDocument, pageSize);
            // 创建PDF表格对象
            float[] colWidthRatio = getColWidthRatio(sheet);
            Table table = new Table(colWidthRatio, true);

            // 添加表格内容
            for (Row row : sheet) {
                for (org.apache.poi.ss.usermodel.Cell cell : row) {
                    com.itextpdf.layout.element.Cell add = new com.itextpdf.layout.element.Cell().add(new com.itextpdf.layout.element.Paragraph(cell.toString()));
                    table.addCell(add);
                }
            }
            // 添加表格到PDF文档
            document.add(table);
            // 关闭PDF文档
            document.close();
        } catch (Exception e) {
            log.error("电子表格导出失败：" + e.getMessage());
        }

    }

    private static float[] getColWidthRatio(Sheet sheet) {
        int firstRowNum = sheet.getFirstRowNum();
        int lastRowNum = sheet.getLastRowNum();

        Row firstRow = sheet.getRow(firstRowNum);
        short firstCellNum = firstRow.getFirstCellNum();
        short lastCellNum = firstRow.getLastCellNum();

        float[] columnWidths = new float[lastCellNum - firstCellNum];
        Arrays.fill(columnWidths, 6);

        for (int rowIndex = firstRowNum; rowIndex <= lastRowNum; rowIndex++) {
            Row row = sheet.getRow(rowIndex);
            for (int cellIndex = firstCellNum; cellIndex < lastCellNum; cellIndex++) {
                Cell cell = row.getCell(cellIndex);
                if (cell != null) {
                    String cellValue = cell.toString().trim();
                    int cellWidth = cellValue.length(); // 以字符数为单位
                    if (columnWidths[cellIndex] < cellWidth) {
                        columnWidths[cellIndex] = cellWidth;
                    }
                }
            }
        }
        return columnWidths;
    }

    private static int getColWidth(Sheet sheet) {
        int rowNum = sheet.getRow(0).getLastCellNum();
        Row row = sheet.getRow(rowNum);
        int cellCount = row.getPhysicalNumberOfCells();
        int sum = 0;

        for (int i = row.getFirstCellNum(); i < cellCount; i++) {
            Cell cell = row.getCell(i);
            if (cell != null) {
                sum += sheet.getColumnWidth(i);
            }
        }
        return sum / 2;
    }


    /**
     * Description: 给pdf文件添加水印<br>
     * @param InPdfFile
     *            要加水印的原pdf文件路径
     * @param outPdfFile
     *            加了水印后要输出的路径
     * @param textMark
     *            水印文字
     * @param textWidth
     *            文字横坐标
     * @param textHeight
     *            文字纵坐标
     * @throws Exception
     * @see
     */
    public static void addPdfTextMark(String InPdfFile, String outPdfFile, String textMark, int textWidth, int textHeight) throws Exception {
        PdfReader reader = new PdfReader(InPdfFile, "PDF".getBytes());
        PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(new File(outPdfFile)));

        PdfContentByte under;

        BaseFont font = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);// 使用系统字体

        int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
        for (int i = 1; i <= pageSize; i++) {
            //under = stamp.getUnderContent(i);// 水印在之前文本下
            under = stamp.getOverContent(i);//水印在之前文本上
            under.beginText();
            under.setColorFill(new BaseColor(245,245,245));// 文字水印 颜色
            under.setFontAndSize(font, 20);// 文字水印 字体及字号
            under.setTextMatrix(textWidth, textHeight);// 文字水印 起始位置
            under.showTextAligned(Element.ALIGN_CENTER, textMark, textWidth, textHeight, 0);
            under.endText();
        }
        stamp.close();// 关闭
        reader.close();
    }

    /**
     * s中的双字节字符设置为中文字体，单字节字符设置为其他字体，返回Phrase
     *  思路：遍历字符串的每个字符，依次得到相同类型(同为双字节或非双字节)的连续字符串，用对应字体创建Chunk加入Paragraph
     * @param s
     * @param chineseFont
     * @param otherFont
     * @return
     */
    public static Paragraph getParagraph(String s, Font chineseFont, Font otherFont) {

        if (s == null || s.equals("")) {
            return new Paragraph();
        }

        Paragraph paragraph = new Paragraph();
        //临时串，用于存放相同类型(中文或者非中文)字符
        StringBuilder tempBuilder = new StringBuilder();
        boolean lastIsChinese = true;
        for (char c : s.toCharArray()) {
            boolean currentIsChinese = RegexUtils.isDoubleByteCharacter(c);
            //如果当前字符和上个字符是同一种字符(都是中文字符，或者都不是中文字符)，则当前字符加入临时串
            if (currentIsChinese == lastIsChinese) {
                tempBuilder.append(c);
            }
            //如果当前字符和上个字符不是一种字符，则把临时串建成chunk加入phrase，清空临时串，然后把当前字符加入临时串，更新上个字符状态
            else {
                paragraph.add(String.valueOf(new Chunk(tempBuilder.toString(), lastIsChinese ? chineseFont : otherFont)));
                //清空临时串
                tempBuilder.setLength(0);
                tempBuilder.append(c);
                lastIsChinese = currentIsChinese;
            }
        }
        //把最后的临时串建成chunk加入phrase
        paragraph.add(new Chunk(tempBuilder.toString(), lastIsChinese ? chineseFont : otherFont));
        return paragraph;
    }

    public static void main(String[] args) {
        try {
            converToPdf("E:\\789.xlsx", "E:\\789.pdf");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
